/* ************************************************************************* */
/*                                                                           */
/* This is the core of the program. It simply calls all the other routines   */
/* in order.                                                                 */
/*                                                                           */
/* ************************************************************************* */
main()
{
    InitTools();            /* initialize tools                             */
    InitApp();              /* initialize application specific stuff        */
    ShowCursor();
    EventLoop();            /* do your stuff                                */
    ShutDownApp();          /* until user wants to                          */
    ShutDownTools();        /*   do something else!                         */
}


/* ************************************************************************* */
/*                                                                           */
/* ErrorCheck - Called by InitTools to check for startup errors.             */
/*                                                                           */
/* ************************************************************************* */

char DeathMsg[] =
    "Fatal error $xxxx has occurred at xxxx. Press any key to exit:";

void ErrorCheck(where)
int where;
{
      if (_toolErr)
     {
       Int2Hex(_toolErr,DeathMsg + 13 ,4);  /* Stick error # into a string  */
       Int2Hex(where,DeathMsg + 34 ,4);     /* Put location # into a string */
       GrafOff();                           /* Turn off Super Hires         */
       WriteCString(DeathMsg);              /* Print the error message      */
       SysBeep();                           /* Danger, Will Robinson!!!     */
       ReadChar(0);                         /* Pause for a character        */
       ShutDownTools();                     /* ShutDown my Tools            */
       exit(1);                             /* Run like a coward            */
     }
}


/* ************************************************************************* */
/*                                                                           */
/* InitTools - This routine start up all the tools that will be needed by    */
/* your application.                                                         */
/*                                                                           */
/* ************************************************************************* */

#define QDZPage     0
#define EMZPage     0x0300      /* QDZPage+0x0300 */
#define CtlZPage    0x0400      /* EMZPage+0x0100 */
#define MenuZPage   0x0500      /* CtlZPage+0x0100 */
#define LEZPage     0x0600      /* MenuZPage+0x0100 */
#define PMZPage     0x0700      /* LEZPage+0x0100 */
#define SFZPage     0x0900      /* PMZPage+0x0200 */
#define FMZPage     0x0A00      /* SFZPage+0x0100 */
#define ToolZPSize  0x0B00L     /* FMZPage+0x0100 */

InitTools()
{
    TLStartUp();                                /* for calling tools */
    ErrorCheck(1);                              /* Make sure all is OK      */
    MyID = MMStartUp();                         /* ID for all transactions */
    ErrorCheck(2);                              /* Make sure all is OK      */
    MTStartUp();                                /* Misc. Tools  */
    ErrorCheck(3);                              /* Make sure all is OK      */

    y = NewHandle(ToolZPSize,
        MyID,                                   /* put it to my name    */
        attrLocked+attrFixed+attrPage+attrBank,
        0L);
    ErrorCheck(4);                              /* Make sure all is OK      */
    z = *y;                                     /* deref handle     */

    LoadTools(ToolTable);
    ErrorCheck(5);                              /* Make sure all is OK      */

    QDStartUp((int) z + QDZPage,ThisMode,MAXSCAN,MyID);
    ErrorCheck(6);                              /* Make sure all is OK      */

    QDAuxStartUp();
    ErrorCheck(16);

    EMStartUp((int) z + EMZPage,20,0,ScreenWidth,0,200,MyID);
    ErrorCheck(7);                              /* Make sure all is OK      */

    MoveTo(30,30);
    SetBackColor(0);
    SetForeColor(0xf);
    DrawString("\pOne Moment Please ... ");

    WaitCursor();
    ShowCursor();

    WindStartUp(MyID);
    ErrorCheck(8);                              /* Make sure all is OK      */

    CtlStartUp(MyID,(int) z + CtlZPage);
    ErrorCheck(9);                              /* Make sure all is OK      */

    MenuStartUp(MyID,(int) z + MenuZPage);
    ErrorCheck(10);                             /* Make sure all is OK      */

    LEStartUp(MyID,(int) z + LEZPage);
    ErrorCheck(11);                             /* Make sure all is OK      */

    DialogStartUp(MyID);
    ErrorCheck(12);                             /* Make sure all is OK      */

    ScrapStartUp();                     /* no errors possible from these 2  */
    DeskStartUp();                          /* All we need is init'ed now   */

    /* Insert application specific tools here */

    PMStartUp(MyID, (int) z + PMZPage );
    ErrorCheck(15);

    SFStartUp(MyID, (int) z + SFZPage);
    ErrorCheck(13);

    FMStartUp(MyID, (int) z + FMZPage);         /* the watch cursor is up   */
    ErrorCheck(14);                             /* while we count the fonts */

    PMLoadDriver(bothDrivers);  /* read this in while "Plz w8" is on screen */

    RefreshDesktop(0L);


}

/* ************************************************************************* */
/*                                                                           */
/* ShutDownTools - Shuts down all of the tools started by InitTools().       */
/*                                                                           */
/* ************************************************************************* */

ShutDownTools()
{
    DeskShutDown();
    FMShutDown();
    PMShutDown();
    SFShutDown();
    ScrapShutDown();
    DialogShutDown();
    LEShutDown();
    MenuShutDown();
    CtlShutDown();
    WindShutDown();
    EMShutDown();
    QDAuxShutDown();
    QDShutDown();
    MTShutDown();

    DisposeHandle(y);

    MMShutDown(MyID);
    TLShutDown();
}


/* ************************************************************************* */
/*                                                                           */
/* InitApp - Create the Dialog box. Get and validate a Print handle. Set up  */
/* some default values (50% reduction, 2 columns, 12 pt Courier, condensed   */
/* print, sideways printing). Dim the "Print" button until a file is selected*/
/* for printing.                                                             */
/*                                                                           */
/* ************************************************************************* */
InitApp()
{
    CtlRecHndl  ctrlItem;
    void ShowError();

    myDialog = GetNewModalDialog(&PrintDialog);
    SetPort((GrafPortPtr)myDialog);

    /* Get a print handle, set up system defaults, then add my own.         */
    PrintHndl = (PrRecHndl) NewHandle(140L,
             MyID,
             attrNoCross+attrLocked,
             0L);
    ErrorCheck(17);

    PrDefault(PrintHndl);
    ShowError(PrError());

    /* Put us into condensed mode                                           */

    SetVSizing(2);

    /* Set number of columns to 2, initialize column EditLine string,       */
    /* update Percent Reduction                                             */
    numCols = 2;
    Int2Dec(numCols,&columnDText[1],1,false);
    SetIText(myDialog,Columns,columnDText);
    SetReduction(100/numCols);

    /* Set orientation to sideways and update Print Handle                  */
    sideways = true;
    SetOrientation(sideways);

    /* Default printout font                                                */
    theFont = (12 << 24) + (0 << 16) + 22; /*12 pt. plain Courier           */

    /* Dim the "Print" item until we get a valid file                       */
    ctrlItem = GetControlDItem(myDialog,Print);
    HiliteControl(255,ctrlItem);

    ShowWindow(myDialog);

    InitCursor();
}



/* ************************************************************************* */
/*                                                                           */
/* ShutDownApp - This routine is called once at the end of your program, but */
/* before the tools are shut down. Take this opportunity to clean up after   */
/* yourself if you need to.                                                  */
/*                                                                           */
/* ************************************************************************* */
ShutDownApp()
{
    /* Currently does nothing */
}



/* ************************************************************************* */
/*                                                                           */
/* ShowError
/*                                                                           */
/* ************************************************************************* */

void ShowError(ErrNum)
int ErrNum;
{
    ptr ErrStringPtr;
    
    if (ErrNum != 0) {
        switch(ErrNum) {
            case prAbort:
                ErrStringPtr = ErrCanceled;
                break;
            case missingDriver:
                ErrStringPtr = ErrMissingDriver;
                break;
            case portNotOn:
                ErrStringPtr = ErrPortNotOn;
                break;
            case noPrintRecord:
                ErrStringPtr = ErrNoPrintRecord;
                break;
            case badLaserPrep:
                ErrStringPtr = ErrBadLaserPrep;
                break;
            case badLPFile:
                ErrStringPtr = ErrBadLPFile;
                break;
            case papConnNotOpen:
                ErrStringPtr = ErrPapConnNotOpen;
                break;
            case papReadWriteErr:
                ErrStringPtr = ErrPapReadWriteErr;
                break;
            case 0x1308:    /* new error code (Sys Disk 3.2) - PntrConFailed */
                ErrStringPtr = ErrPntrConFailed;
                break;
            default:
                ErrStringPtr = 0;
        } /* switch */
        
        if (ErrStringPtr != 0) {
            AlertWindow(0,NULL,ErrStringPtr);
        } else {
            Int2Hex(PrError(),PrintErrNum,4);
            AlertWindow(0,SubStrings,ErrGeneric);
        }
        
    } /* If (ErrNum) */
} /* ShowError() */
    
    
/* ************************************************************************* */
/*                                                                           */
/*  Bring up the About box in response to clicking on the About button.      */
/*  This routine employs some high-powered pyro-techniks designed by         */
/*  Industrial Light and Magic when displaying the About box, to wit, it     */
/*  draws a series of rectangles to creating that lovely Zooming effect.     */
/*  When closing the box, the process is reversed. Neat, huh!?!              */
/*                                                                           */
/* ************************************************************************* */

#define ZOOMMAX 9
void doAbout()
{
    GrafPortPtr tDialog;
    Rect        startRect,newRect,oldRect,endRect,deltaRect;
    int         i;

    /* Zoom out from the About button to where the About window will be */

    startRect = aboutButton.itemRect;
    endRect = AboutDialog.dtBoundsRect;
    INSETRECT(endRect,-12,-5);
    GlobalToLocal((PointPtr) &endRect.v1);
    GlobalToLocal((PointPtr) &endRect.v2);

    /* define some delta constants for speed                            */
    SETRECT(deltaRect,
                endRect.v1-startRect.v1,
                endRect.h1-startRect.h1,
                endRect.v2-startRect.v2,
                endRect.h2-startRect.h2);

    /* set up my pen size and mode                                      */
    SetPenSize(2,1);
    SetPenMode(notXOR);

    /* Now draw appropriately sized rectangles                          */
    for (i = 1; i <= ZOOMMAX; i++) {
        SETRECT(newRect,
                    startRect.v1 + (deltaRect.v1*i)/ZOOMMAX,
                    startRect.h1 + (deltaRect.h1*i)/ZOOMMAX,
                    startRect.v2 + (deltaRect.v2*i)/ZOOMMAX,
                    startRect.h2 + (deltaRect.h2*i)/ZOOMMAX);
        FrameRect(&newRect);
    }

    /* Then erase all of them but the last one. It will stay around     */
    /* and pretend like it was supposed to be there all along by        */
    /* looking just like an Alert window's frame.                       */

    for (i = 1; i < ZOOMMAX; i++) {
        SETRECT(newRect,
                    startRect.v1 + (deltaRect.v1*i)/ZOOMMAX,
                    startRect.h1 + (deltaRect.h1*i)/ZOOMMAX,
                    startRect.v2 + (deltaRect.v2*i)/ZOOMMAX,
                    startRect.h2 + (deltaRect.h2*i)/ZOOMMAX);
        FrameRect(&newRect);
    }

    /* Now redraw the last rectangle in modeOr. We originally drew it   */
    /* in modeXOR, which created weird color effects. So redraw it with */
    /* the right colors.                                                */

    SetPenMode(modeCopy);
    FrameRect(&endRect);

    /* Now empty out the inside of the rectangle. This would have been  */
    /* done by the Window Manager anyway when it drew the Alert window, */
    /* but I want to do it now for speed.                               */

    INSETRECT(endRect,2,1);
    EraseRect(&endRect);

    /* Finally, all of the fun stuff is over. Get and handle the Modal  */
    /* Dialog, and then close it.                                       */

    tDialog = GetNewModalDialog(&AboutDialog);
    ModalDialog(NULL);
    CloseDialog(tDialog);

    /* Now reverse the entire process of zooming the window.            */

    SetPort((GrafPortPtr)myDialog);
    SetPenSize(2,1);
    SetPenMode(notXOR);

    for (i = ZOOMMAX; i >= 1; i--) {
        SETRECT(newRect,
                    startRect.v1 + (deltaRect.v1*i)/ZOOMMAX,
                    startRect.h1 + (deltaRect.h1*i)/ZOOMMAX,
                    startRect.v2 + (deltaRect.v2*i)/ZOOMMAX,
                    startRect.h2 + (deltaRect.h2*i)/ZOOMMAX);
        FrameRect(&newRect);
    }

    for (i = ZOOMMAX; i >= 1; i--) {
        SETRECT(newRect,
                    startRect.v1 + (deltaRect.v1*i)/ZOOMMAX,
                    startRect.h1 + (deltaRect.h1*i)/ZOOMMAX,
                    startRect.v2 + (deltaRect.v2*i)/ZOOMMAX,
                    startRect.h2 + (deltaRect.h2*i)/ZOOMMAX);
        FrameRect(&newRect);
    }

    PenNormal();
}



/* ************************************************************************* */
/*                                                                           */
/*  This routine sets the condensed/middle/normal vertical aspect ratios     */
/*  in the print record for the currently selected printer. Enter with:      */
/*
/*      0 = Normal
/*      1 = Intermediate
/*      2 = Condensed
/*                                                                           */
/* ************************************************************************* */

void SetVSizing(newSize)
int newSize;
{
    int printer;

    theVSizing = newSize;
    printer = (**PrintHndl).prInfo.iDev;    /* what kind of printer?        */
    if (printer == 1) {

        /* We have an ImageWriter. This printer does not have an Inter-     */
        /* mediate mode, so we force that into Condensed mode.              */

        switch (newSize) {
            case 0:
                (**PrintHndl).prStl.wDev |=  0x0004;    /* Set bit 2        */
                break;
            case 1:
            case 2:
                (**PrintHndl).prStl.wDev &= ~0x0004;    /* Clear bit 2      */
                break;
        }
    } else {

        /* We are dealing with a LaserWriter. It can take whatever we throw */
        /* at it.                                                           */

        (**PrintHndl).prStl.vSizing = newSize;
    }
}


/* ************************************************************************* */
/*                                                                           */
/*  This routine takes a suggested amount of percent reduction, and sets the */
/*  print record accordingly. In the case of the ImageWriter, not all red-   */
/*  unctions are possible, so the suggested amount of reduction must be      */
/*  adjusted accordingly. When all of that has been done, convert the amount */
/*  of reduction to text, and set that as the Percent Reduction EditLine     */
/*  field.                                                                   */
/*                                                                           */
/* ************************************************************************* */

void SetReduction(suggestedReduction)
int suggestedReduction;
{
    int printer;

    printer = (**PrintHndl).prInfo.iDev;    /* what kind of printer?        */
    if (printer == 1) {

        /* We are dealing with an ImageWriter. These little beaties can     */
        /* only print in 100% or 50% reduction. Therefore, examine the      */
        /* suggested amount of reduction, and if it is over 75%, set it to  */
        /* 100%; if it is under 75%, set it to 50%. Then set or clear the   */
        /* reduction bit in the wDev field appropriately (0 for 50%, 1 for  */
        /* full sized).                                                     */

        if (suggestedReduction > 75) {
            theReduction = 100;
            (**PrintHndl).prStl.wDev |=  0x0008;    /* Set bit 3            */
        } else {
            theReduction = 50;
            (**PrintHndl).prStl.wDev &= ~0x0008;    /* Clear bit 3          */
        }
    } else {

        /* We are dealing with a LaserWriter. If it is between 25 and 400   */
        /* inclusive, then set theReduction to it, and set the appropriate  */
        /* field in the print record. If it is NOT between 25 and 400, then */
        /* ignore 'suggestedReduction' and reset the EditLine item back to  */
        /* the previous value of theReduction.                              */

        if ((suggestedReduction >= 25) && (suggestedReduction <= 400)) {
            theReduction = suggestedReduction;
            (**PrintHndl).prStl.reduction = theReduction;
        }
    }
    Int2Dec(theReduction,&percentDText[1],(theReduction>99)?3:2,false);
    percentDText[0] = (char)(theReduction>99)?3:2;
    SetIText(myDialog,Percent,percentDText);
}


/* ************************************************************************* */
/*                                                                           */
/*  This routine is called from all over the place to set the orientation    */
/*  bit (bit 1 of prStl.wDev) in the print record according to the following */
/*  table:                                                                   */
/*                                                                           */
/*                      Portrait    Landscape
/*                      (upright)   (sideways)
/*      LaserWriter         0           1
/*      ImageWriter         1           0
/*                                                                           */
/*                                                                           */
/* ************************************************************************* */

void SetOrientation(sideways)
boolean sideways;
{
    int printer;

    printer = (**PrintHndl).prInfo.iDev;    /* get printer type             */

    /* If the printer is an ImageWriter and we are printing sideways,       */
    /* or the printer is a LaserWriter and we are printing upright,         */
    /* clear the orientation bit (bit 1 of wDev). Otherwise, set it.        */

    if (((printer==1) && sideways) || ((printer==3) && (!sideways))) {
        (**PrintHndl).prStl.wDev &= ~0x0002;    /* Clear bit 1              */
    } else {
        (**PrintHndl).prStl.wDev |=  0x0002;    /* Set bit 1                */
    }
}


/* ************************************************************************* */
/*                                                                           */
/*  The user has clicked on one of the orientation icons. Find out which one */
/*  determine if we need to change their states, and invert the icons if we  */
/*  do. The call a routine to set the appropriate field in the print record. */
/*                                                                           */
/* ************************************************************************* */

void doPrDirection(what)
word    what;
{
    if (((what == Portrait) && (sideways)) ||
        ((what == Landscape) && (!sideways))) {

        /* What the above line says is: "Has the setting changed?" If so,   */
        /* we invert the icons, change our 'sideways' variable, and call a  */
        /* routine to set the Print record.                                 */

        InvertRect(&portraitButton.itemRect);
        InvertRect(&landscapeButton.itemRect);
        sideways = !sideways;
        SetOrientation(sideways);
    }
}


/* ************************************************************************* */
/*                                                                           */
/*  An event occurred in the "Percent Reduction" field. Get the text that's  */
/*  there, turn it into a number, and validate it.                           */
/*                                                                           */
/* ************************************************************************* */

void doPercent()
{
    char    theText[5];
    int     temp;

    GetIText(myDialog,Percent,theText); /* Get the text as a Pascal String  */

    /* set temp = value of text in columns EditLine item                    */
    if ((int)(*theText) > 0) {
        temp = Dec2Int(&theText[1],(int)(*theText),false);
    } else {
        temp = 0;
    }
    if (temp != theReduction) SetReduction(temp);
}


/* ************************************************************************* */
/*                                                                           */
/*  An event occured in the "Number of Columns" EditLine box. Get the        */
/*  text that's in there, turn it into a number, and validate that number.   */
/*                                                                           */
/* ************************************************************************* */

void doColumns()
{
    char    theText[5];
    int     temp;

    GetIText(myDialog,Columns,theText); /* Get the text as a Pascal String  */
    if ((int) (*theText) > 0) {         /* If length > 0, validate it.      */

        /* set temp = value of text in columns EditLine item                */
        temp = Dec2Int(&theText[1],(int)(*theText),false);

        /* If it is between 1 and 4 inclusive, then set numCols to it, and  */
        /* fabricate an appropriate value for the amount of reduction. If   */
        /* it is NOT between 1 and 4, then reset the EditLine item back to  */
        /* the previous value of numCols.                                   */

        if ((temp > 0) && (temp < 5)) {
            numCols = temp;
            SetReduction(100/numCols);
        } else {
            Int2Dec(numCols,&columnDText[1],1,false);
            SetIText(myDialog,Columns,columnDText);
        }
    }
}


/* ************************************************************************* */
/*                                                                           */
/*  The Use Borders check box has been clicked on. Invert its value, and     */
/*  redraw the border lines.                                                 */
/*                                                                           */
/* ************************************************************************* */

void doCheckBox()
{
    myBorders[0].used = !myBorders[0].used;
    SetDItemValue(myBorders[0].used?0:1,myDialog,UseBorder);
    DrawUserItem(myDialog,Borders);
}


/* ************************************************************************* */
/*                                                                           */
/*  This routine is called if we click on our border control. Find out       */
/*  which one was clicked on, invert its status, and redraw it.              */
/*                                                                           */
/* ************************************************************************* */

void doBorders()
{
    Point   *mouseLoc;
    int     index;
    void DrawLine();

    GetMouse(mouseLoc);                 /* Find out where we clicked        */

    for (index=1;                       /* See if we hit a border line      */
        !(PtInRect(mouseLoc,&myBorders[index].line) || (index == 8));
        index++ );

    if (PtInRect(mouseLoc,&myBorders[index].line)) {    /* invert it if so  */
        myBorders[index].used = !myBorders[index].used;
        DrawLine(index);
        PenNormal();
    }
}


/* ************************************************************************* */
/*                                                                           */
/*  Called in response to clicking on the File button. It calls SFGetFile    */
/*  to get a file name. If we get one, then we activate the Print button.    */
/*  if we don't get one, then we deactivate that button.                     */
/*                                                                           */
/* ************************************************************************* */

void doChFile()
{
    CtlRecHndl ctrlItem;

    SFGetFile(120,20,prompt,NULL,myTypes,&myReply);
    if (myReply.good) {
        ctrlItem = GetControlDItem(myDialog,Print); /* Activate Print button */
        HiliteControl(0,ctrlItem);
    } else {
        ctrlItem = GetControlDItem(myDialog,Print); /* Deactivate it.       */
        HiliteControl(255,ctrlItem);
    }
}


/* ************************************************************************* */
/*                                                                           */
/*  Called in response to clicking on the Choose Printer button. It calls    */
/*  PrChoosePrinter() to select the printer, sets default values in the      */
/*  print record, and then restores as many of them as we can to the settings*/
/*  wehad before the change was made.                                        */
/*                                                                           */
/* ************************************************************************* */

void doChPrinter()
{
    boolean dummy;
    word    oldFeed, oldPaperType;

    oldFeed = (**PrintHndl).prStl.feed;
    oldPaperType = (**PrintHndl).prStl.paperType;

    dummy = PrChooser();
    PrDefault(PrintHndl);
    SetOrientation(sideways);
    SetReduction(theReduction);
    SetVSizing(theVSizing);

    (**PrintHndl).prStl.feed = oldFeed;
    (**PrintHndl).prStl.paperType = oldPaperType;
}


/* ************************************************************************* */
/*                                                                           */
/*  This routine is called in response to pressing the Choose Font button.   */
/*  It simply calls ChooseFont() and saves the result in 'theFont'. However, */
/*  page 8-27 of the ToolBox reference manual says that ChooseFont auto-     */
/*  matically installs the font chosen. For this reason, I save off the      */
/*  current font before calling ChooseFont(), and restore it afterwards.     */
/*                                                                           */
/* ************************************************************************* */

void doChFont()
{
    LongWord oldFont;

    /* There is a bug in some System Disks that cause the computer to hang  */
    /* if we call ChooseFont while there are updates pending in the dialog  */
    /* box. Let's get rid of them before we call it, why don't we...        */

    BeginUpdate(myDialog);
    DrawDialog(myDialog);
    EndUpdate(myDialog);

    oldFont = FMGetCurFID();            /* Save the old port font           */
    theFont =  ChooseFont(theFont,0);   /* Get the new one                  */
    InstallFont(oldFont,0);             /* Set the old port font back       */
}


/* ************************************************************************* */
/*                                                                           */
/*  This routine is called in response to pressing the Page Setup button.    */
/*  It calls the Page Setup routine in the Print Manager. It then sets up    */
/*  some variables that we maintain based on the new settings in the Print   */
/*  record. For instance, it will invert the correct Portrait or Landscape   */
/*  icon, and will set the right number in the % Reduction box.              */
/*                                                                           */
/* ************************************************************************* */

void doPgSetup()
{
    int dummy, printer,bit1;
    boolean newSideways;


    if (PrintHndl != NULL) {
        dummy = PrStlDialog(PrintHndl);     /* Call PrStlDialog             */
        printer = (**PrintHndl).prInfo.iDev;/* determine type of printer    */


        /* Update our % reduction display and VSizing variable.             */

        if (printer == 1) {
            SetReduction(((**PrintHndl).prStl.wDev & 0x0008)?100:50);
            if (((**PrintHndl).prStl.vSizing & 0x0004) == 0) {
                theVSizing = 2;
            } else {
                theVSizing = 0;
            }
        } else {
            SetReduction((**PrintHndl).prStl.reduction);
            theVSizing = (**PrintHndl).prStl.vSizing;
        }



        /* Determine whether the user selected Portrait or Landscape        */
        /* printing. If the orientation changed, then invert our icons.     */

        bit1 = (**PrintHndl).prStl.wDev & 0x0002;  /* get bit 1             */
        switch (printer) {
            case 1: newSideways = (bit1==0); break;
            case 3: newSideways = (bit1!=0); break;
            default: newSideways = false; break;
        }
        if (sideways != newSideways) {
            sideways = newSideways;
            InvertRect(&portraitButton.itemRect);
            InvertRect(&landscapeButton.itemRect);
        }
    }
}
